package ldh.im.fxbase.service;

import ldh.im.dto.business.item.CollectInfoItem;
import ldh.im.exception.ImServiceException;
import ldh.im.fxbase.dao.ImCollectDao;
import ldh.im.fxbase.dao.ImMessageDao;
import ldh.im.fxbase.data.pojo.ImCollect;
import ldh.im.fxbase.data.pojo.ImMessage;
import ldh.im.fxbase.data.pojo.MessageExt;
import ldh.im.fxbase.data.pojo.status.ImCollectContent;
import ldh.im.fxbase.data.pojo.status.ImCollectStatus;
import ldh.im.fxbase.exception.ImErrorCode;
import ldh.im.fxbase.util.BeanFactory;
import ldh.im.fxbase.util.RpcUtil;
import ldh.im.util.ConfigUtil;
import ldh.im.util.DateUtil;
import ldh.rpc.util.JsonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

public class CollectService {

    private static final Logger LOGGER = LoggerFactory.getLogger(CollectService.class);

    private ImCollectDao collectDao = BeanFactory.getInstance().getBean(ImCollectDao.class);
    private ImMessageDao messageDao = BeanFactory.getInstance().getBean(ImMessageDao.class);

    /**
     * 收藏同步
     * @param userId
     * @param collectInfoItems
     * @throws Exception
     */
    public void doCollectBusiness(String userId, List<CollectInfoItem> collectInfoItems) throws Exception {
        if (collectInfoItems.size() < 1) return;

        List<ImCollect> imCollectList = collectInfoItems.stream().map(cinfo->toCollect(userId, cinfo)).collect(Collectors.toList());

        saveOrUpdate(userId, imCollectList);
    }


    /**
     * 迁移需要收藏消息中的附件
     * @param imMessage
     */
    public boolean collectMoveMessageAttachFile(String userId, ImMessage imMessage) throws Exception {
        if (!imMessage.isAttachFile()) return false;
        boolean isChange = false;
        String root = ConfigUtil.getRoot();
        LocalDateTime now = LocalDateTime.now();
        String collectDir = ConfigUtil.buildFileDir("collect", DateUtil.toDate(now), userId);
        if (Files.notExists(Paths.get(root + collectDir))) {
            Files.createDirectories(Paths.get(root + collectDir));
        }
        MessageExt messageExt = imMessage.getMessageExt();
        if (!messageExt.getFileUrl().contains("collect")) { // 未迁移
            if (messageExt.getRemote()) {
                String fromFile = root + messageExt.getFileUrl();
                String toFile = root + collectDir + File.separator + messageExt.getFileName();
                Files.move(Paths.get(fromFile), Paths.get(toFile));

                messageExt.setFileUrl(collectDir + File.separator + messageExt.getFileName());
                imMessage.setContent(collectDir + File.separator + messageExt.getFileName());
                imMessage.setMessageExt(messageExt);
                imMessage.initExt();
                imMessage.setUpdateDateTime(new Date());
                messageDao.update(imMessage);

                isChange = true;
            }
        }

        if (imMessage.isRef()) {
            String[] serverIds = imMessage.getRefMessageIds().split(",");
            List<ImMessage> imMessageList = messageDao.getByServerIdsAndUserId(Arrays.stream(serverIds).collect(Collectors.toSet()), userId);
            imMessage.setRefMessages(imMessageList);
            for (ImMessage message : imMessageList) {
                boolean isRefChange = collectMoveMessageAttachFile(userId, message);
                if (!isChange) isChange = isRefChange;
            }
        }
        return isChange;
    }

    private void saveOrUpdate(String userId, List<ImCollect> imCollectList) throws Exception {
        Set<ImCollect> insertImCollectSet = new LinkedHashSet<>();
        Set<ImCollect> updateImCollectSet = new LinkedHashSet<>();

        for(ImCollect imCollect : imCollectList) {
            ImCollect dbCollect = collectDao.getByKey(imCollect.getUserId(), imCollect.getSessionId(), imCollect.getMessageId());
            if (dbCollect == null) {
                insertImCollectSet.add(imCollect);
            } else {
                imCollect.setId(dbCollect.getId());
                updateImCollectSet.add(imCollect);
            }
        }
        if (insertImCollectSet.size() > 0) {
            collectDao.batchInserts(insertImCollectSet.stream().collect(Collectors.toList()));
        }
        if (updateImCollectSet.size() > 0) {
            collectDao.batchUpdate(updateImCollectSet.stream().collect(Collectors.toList()));
        }

        downAttachFile(userId, imCollectList);
    }

    // 下载附件
    private void downAttachFile(String userId, List<ImCollect> imCollectList) throws Exception {
        for(ImCollect collect : imCollectList) {
            ImMessage message = messageDao.getMessageByServerId(userId, collect.getMessageId());
            if (message != null) {
                boolean isChange = collectMoveMessageAttachFile(userId, message);
                if (isChange) {
                    ImCollectContent imCollectContent = new ImCollectContent(message);
                    collect.setCollectContent(imCollectContent);
                    collectDao.update(collect);
                }
            } else {
                downAttachFileFromServer(userId, collect);
            }
        }
    }

    private void downAttachFileFromServer(String userId, ImCollect collect) {
        RpcUtil.getImService().downloadFile(collect);
    }

    private ImCollect toCollect(String userId, CollectInfoItem cinfo) {
        ImCollect collect = new ImCollect();
        collect.setUserId(userId);
        collect.setSessionId(cinfo.getSessionId());
        collect.setMessageId(cinfo.getMessageId());
        collect.setServerId(cinfo.getServerId());
        collect.setMessageType(cinfo.getMessageType());
        collect.setContent(cinfo.getContent());
        collect.setLabelIds(cinfo.getLabelIds());
        collect.setStatus(ImCollectStatus.wrap(cinfo.getStatus()));

        buildContent(userId, collect);
        return collect;
    }

    private void buildContent(String userId, ImCollect collect) {
        try {
            String messageId = collect.getMessageId();
            ImMessage imMessage = messageDao.getMessageByServerId(userId, messageId);
            ImCollectContent collectContent = new ImCollectContent(imMessage);
            collect.setContent(JsonUtil.toJson(collectContent));
        } catch (Exception e) {
            LOGGER.error("加载消息失败", e);
            throw new ImServiceException(ImErrorCode.SystemError);
        }

    }
}
